﻿using Complier.LexicalAnalysis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Complier.CodeGenerator;
using Complier.Model;
using Complier.Model.Ast;
using Complier.Model.Tokens;
using Complier.SyntaxAnalysis;
using 编译器.Properties;

namespace 编译器
{
    public partial class Form1 : Form
    {
        #region 自定义变量
        /// <summary>
        /// 源代码
        /// </summary>
        string code = string.Empty;
        /// <summary>
        /// 默认源代码
        /// </summary>
        string defaultCode = string.Empty;
        /// <summary>
        /// 词法分析结果，单词数组
        /// </summary>
        private Token[] tokens;
        /// <summary>
        /// 语法树
        /// </summary>
        private ProgramNode ast;
        /// <summary>
        /// 符号表
        /// </summary>
        private List<Parser.Vartable> vartables;
        /// <summary>
        /// 四元式
        /// </summary>
        private List<QuaternionTypeTable._Siyuanshi> siyuanshi;
        /// <summary>
        /// 词法分析显示结果
        /// </summary>
        private StringBuilder _tokenAnalysisStr;
        
        /// <summary>
        /// 语法分析显示结果
        /// </summary>
        private StringBuilder _parseStr;
        /// <summary>
        /// 语义分析显示结果
        /// </summary>
        private StringBuilder _quaStr;
        /// <summary>
        /// 中间代码生成显示结果
        /// </summary>
        private StringBuilder _codeStr;
        /// <summary>
        /// 编译运行结果
        /// </summary>
        private StringBuilder _complierStr;

        #endregion
        #region 自定义方法
        /// <summary>
        /// 读取源文件文本内容
        /// </summary>
        /// <param name="path">源代码文件路径</param>
        string GetFileText(string path)
        {
            StreamReader sr = null;
            try
            {
                sr = File.OpenText(path);
                //显示源文件内容
                return sr.ReadToEnd();
            }

            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
            finally
            {
                sr?.Dispose();
            }
            return defaultCode;
        }
        /// <summary>
        /// 词法分析
        /// </summary>
        private void TokenAnalysis()
        {
            if (textBox2.Text.Length <= 0) return;
            code=textBox2.Text ;

            _tokenAnalysisStr = new StringBuilder();

            var lexer = new Tokenizer(code);
            //词法分析结果
            tokens = lexer.Tokenize();

            _tokenAnalysisStr.AppendLine("***********************词法分析************************");

            _tokenAnalysisStr.AppendLine("\t序号\t单词\t类型\t\t\t行号\r\n");
            for (int i = 0; i < tokens.Length; i++)
            {
                _tokenAnalysisStr.AppendLine($"\t{i + 1}\t{tokens[i]}");

            }

            var errTokens = tokens.Where(o => o.GetType().Name == "UnKnowToken");
            var enumerable = errTokens as Token[] ?? errTokens.ToArray();
            if (enumerable.Any())
            {
                _tokenAnalysisStr.AppendLine("\r\n语法分析发现错误;");
                textBox1.Text+="\r\n语法分析发现错误\r\n";
                foreach (var token in enumerable)
                {
                    var item = (UnKnowToken)token;
                    _tokenAnalysisStr.AppendLine($"\r\n\t 第{item.LineNum}行 {item.Content} 出错：{item.ErrText}");
                    textBox1.Text += $"\r\n\t 第{item.LineNum}行 {item.Content} 出错：{item.ErrText}\r\n";

                }

            }

            //显示词法分析结果
            label5.Text = "词法分析";
            textBox4.Text = _tokenAnalysisStr.ToString();
        }
        /// <summary>
        /// 语法分析
        /// </summary>
        private void Parse()
        {
            //_parseStr += "-----------语法分析(自顶向下)：---------\r\n";
            //complier.parse(ref _parseStr);

            _parseStr = new StringBuilder();

            //_parseStr.AppendLine("**********************语法分析*************************");
            Console.ResetColor();
            var parser = new Parser(tokens);
            //分析之后的语法树
            ast = parser.ParseToAst();
            vartables = parser.vartable;
            _parseStr.AppendLine("**********************符号表*************************");
            _parseStr.AppendLine("序号\t变量名\t类型\t所在节点");

            for (int i = 0; i < parser.vartable.Count; i++)
            {
                _parseStr.AppendLine($"{i + 1}\t{parser.vartable[i].name}\t{parser.vartable[i].type}\t{parser.vartable[i].nodeType.GetType().Name}");

            }


            label5.Text = "语法分析";
            textBox4.Text = _parseStr.ToString();
        }
        /// <summary>
        /// 生成四元式
        /// </summary>
        void Quaternion()
        {
            _quaStr = new StringBuilder();
            _quaStr.AppendLine();
            _quaStr.AppendLine("**********************四元式*************************");

            _quaStr.AppendLine($"{"序号",-6}{"类型",-6}{"操作数一",-6}{"操作数二",-6}结果");

            //四元式表
            siyuanshi = new List<QuaternionTypeTable._Siyuanshi>();
            QuaternionTypeTable table = new QuaternionTypeTable(ast, vartables, ref siyuanshi);
            //调用转换方法
            table.PrintAst(ast);
            //输出结果
            for (int i = 0; i < siyuanshi.Count; i++)
            {
                var item = siyuanshi[i];
                _quaStr.AppendLine($"{i + 1,-4}({item.op,6} ,{item.oper1,8} ,{item.oper2,8} ,{item.result,6}    )");
            }
            if (table.Errors.HasErros)
            {
                _quaStr.AppendLine("\r\n错误：");
                textBox1.Text += $"\r\n语义分析出错：";


                for (int i = 0; i < table.Errors.ErrorTexts.Count; i++)
                {
                    _quaStr.AppendLine($"\t{table.Errors.ErrorTexts[i]}");
                    textBox1.Text += $"\r\n\t{table.Errors.ErrorTexts[i]}";
                }
            }
            label5.Text = "语义分析";
            textBox4.Text = _quaStr.ToString();
        }

        /// <summary>
        /// 语义分析和汇编代码生成
        /// </summary>
        private void Code()
        {
            //_codeStr += "-------语义分析和汇编代码生成：--------\r\n";
            //complier.code(ref _codeStr);
            _codeStr=new StringBuilder();

            _codeStr.AppendLine("************中间代码生成和汇编代码生成**********");
            var codeGenerate = new AssemblyGenerate();
            var AssemblyCode = codeGenerate.Code(siyuanshi);
            _codeStr.AppendLine(AssemblyCode);
            label5.Text = "中间代码生成";
            textBox4.Text = _codeStr.ToString();
        }

        void Complier()
        {
            _complierStr=new StringBuilder();
            _complierStr.AppendLine("*********************编译***********************");
            Complier.Complier.Complier complier = new Complier.Complier.Complier();
            var comCode = complier.GenerateCode(code);
            var comResult = complier.Compile(comCode);
            complier.ShowCompileResult(comResult);

            textBox1.Text= complier.ShowCompileResult(comResult);
        }

        #endregion

        public Form1()
        {
            InitializeComponent();
            #region 源程序
            defaultCode = @"
int a = 16;

int func(int b,int bb)
{
    int c = (5*b)+7*bb;
    return c;
}

int main()
{
    a = 16;
    a=func(4,8);
    return a;
}";
            code = defaultCode;

            defaultCode = @"
int main()
{
    int sum = 0;
    int a = 6;
    while(a > 0)
    {
        sum = sum + a;
        a = a - 1;
    }
    return sum;
}";
            //code = defaultCode;

            #endregion

            textBox2.Text = code;
            TokenAnalysis();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            string _path;
            if (File.Exists(@"D:\Downloads\Desktop\test.txt"))
            {
                _path = @"D:\Downloads\Desktop\test.txt";
            }
            else
            {
                //打开文件选择框，选择文件路径
                var ofd = new OpenFileDialog { Filter = Resources.文本筛选字符串 };
                if (ofd.ShowDialog() != DialogResult.OK) return;
                _path = ofd.FileName;
            }

            textBox3.Text = _path;
            comboBox1.SelectedIndex = 0;

            textBox2.Text = GetFileText(_path);
            TokenAnalysis();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            switch (comboBox1.SelectedIndex)
            {
                case 0:
                    label3.Text = "1";
                    TokenAnalysis();
                    break;
                case 1:
                    label3.Text = "2";
                    TokenAnalysis();
                    Parse();
                    break;
                case 2:
                    label3.Text = "3";
                    TokenAnalysis();
                    Parse();
                    Quaternion();
                    break;
                case 3:
                    label3.Text = "4";
                    TokenAnalysis();
                    Parse();
                    Quaternion();
                    Code();
                    Complier();
                    break;
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {

        }
    }
}
